package cn.lixu.basic.service.impl;

import cn.lixu.basic.exception.BusinessException;
import cn.lixu.basic.service.IVerifyService;
import cn.lixu.basic.util.StrUtils;
import cn.lixu.basic.util.VerifyCodeUtils;
import cn.lixu.basic.constant.RegisterConstant;
import cn.lixu.user.domain.User;
import cn.lixu.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class VerifyServiceImpl implements IVerifyService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Override
    public String getImgCode(String key) {
        //判断key是否为空
        if (StringUtils.isEmpty(key)) {
            throw new BusinessException("key为空");
        }

        //获取随机验证码
        //String code = VerifyCodeUtils.generateVerifyCode(6);  这个也可以使用
        String code = StrUtils.getComplexRandomString(4);
        //将验证码存放到redis，设置5分钟过期
        redisTemplate.opsForValue().set(key, code, 5, TimeUnit.MINUTES);

        //把验证码的值合并到图片，使用Base64编码。并返回base64编码的字符串
        return VerifyCodeUtils.verifyCode(110, 40, code);
    }

    @Override
    public void sendSmsCode(Map<String, String> map) {
        //获取手机号
        String phone = map.get("phone");
        //图形验证码对应的key值
        String imageCodeKey = map.get("imageCodeKey");
        //图形验证码
        String imageCode = map.get("imageCode");

        //1.校验参数是否为空
        //1.1   手机号码是否为空
        if (StringUtils.isEmpty(phone)) {
            throw new BusinessException("手机号不可为空");
        }
        //1.2   图形验证码对应的key值是否为空
        if (StringUtils.isEmpty(imageCodeKey)) {
            throw new BusinessException("请刷新页面重新获取图片验证码");
        }
        //1.3   图形验证码是否为空
        if (StringUtils.isEmpty(imageCode)) {
            throw new BusinessException("图片验证码不能为空");
        }

        // 2. 图形验证码校验
        //2.1.图片验证码是否过期
        Object imageCodeValue = redisTemplate.opsForValue().get(imageCodeKey);

        if (imageCodeValue == null) {
            throw new BusinessException("图片验证码过期，请重新获取");
        }
        //2.2.图片验证码是否正确【不区分大小写】
        if (!imageCodeValue.toString().equalsIgnoreCase(imageCode)) {
            throw new BusinessException("错误的图片验证码，请重新输入");
        }
        //3.校验 - 手机号是否被注册
        //通过手机号码查询user对象
        User user = userMapper.loadByPhone(phone);
        if (user != null) {//号码已经存在
            throw new BusinessException("该手机号码已经注册，请直接登录!");
        }

        /**
         * key: 手机号+业务键   业务键：最好是常量  phone + RegisterConstant.PHONEREGISTER
         * value: code:时间戳  code + ":" + System.currentTimeMillis()
         */
        // 4.1 判断是否是第一次发送请求，或者是验证码过期  从redis中取
        Object value = redisTemplate.opsForValue().get(phone + RegisterConstant.PHONEREGISTER);

        String code = null;
        //如果取不到，没有发送过，获取过期了， 直接生成一个新的验证码保存到redis
        if (value == null) {//没有取到值
            code = StrUtils.getComplexRandomString(6);//验证码位数
        } else {//4.2如果取到了，判断是否超过1分钟
            String redisTime = value.toString().split(":")[1];//redisTime 为截取的时间戳
            Long ltime = Long.valueOf(redisTime);//将时间戳转换为Long类型
            if (System.currentTimeMillis() - ltime < 1 * 60 * 1000) {//4.2.1没过重发时间
                throw new BusinessException("一分钟之内不能多次获取验证码！");

            } else {
                // 4.2.2： 如果超过了一分钟，
                code = value.toString().split(":")[0];

            }
        }
        //把code存入redis中，刷新过期时间
        redisTemplate.opsForValue().set(
                phone + RegisterConstant.PHONEREGISTER,
                code + ":" + System.currentTimeMillis(),
                3,
                TimeUnit.MINUTES
        );
        //发短信
        //SmsUtil.sendSms(phone, "你的验证码为：" + code + "，请在3分钟之内使用!" );  //有次数
        System.out.println("你的验证码为：" + code + "，请在3分钟之内使用!");//可以这样测试
    }

    /**
     * 微信绑定验证码
     *
     * @param map
     */
    @Override
    public void binderSmsCode(Map<String, String> map) { //获取手机号
        String phone = map.get("phone");
        //图形验证码对应的key值

        //1.校验参数是否为空
        //1.1   手机号码是否为空
        if (StringUtils.isEmpty(phone)) {
            throw new BusinessException("手机号不可为空");
        }

        /**
         * key: 手机号+业务键   业务键：最好是常量  phone + RegisterConstant.PHONEREGISTER
         * value: code:时间戳  code + ":" + System.currentTimeMillis()
         */
        // 4.1 判断是否是第一次发送请求，或者是验证码过期  从redis中取
        Object value = redisTemplate.opsForValue().get(phone + RegisterConstant.WXBINDER);

        String code = null;
        //如果取不到，没有发送过，获取过期了， 直接生成一个新的验证码保存到redis
        if (value == null) {//没有取到值
            code = StrUtils.getComplexRandomString(6);//验证码位数
        } else {//4.2如果取到了，判断是否超过1分钟
            String redisTime = value.toString().split(":")[1];//redisTime 为截取的时间戳
            Long ltime = Long.valueOf(redisTime);//将时间戳转换为Long类型
            if (System.currentTimeMillis() - ltime < 1 * 60 * 1000) {//4.2.1没过重发时间
                throw new BusinessException("一分钟之内不能多次获取验证码！");

            } else {
                // 4.2.2： 如果超过了一分钟，
                code = value.toString().split(":")[0];

            }
        }
        //把code存入redis中，刷新过期时间
        redisTemplate.opsForValue().set(
                phone + RegisterConstant.WXBINDER,
                code + ":" + System.currentTimeMillis(),
                3,
                TimeUnit.MINUTES
        );
        //发短信
        //SmsUtil.sendSms(phone, "你的验证码为：" + code + "，请在3分钟之内使用!" );  //有次数
        System.out.println("你的验证码为：" + code + "，请在3分钟之内使用!");//可以这样测试

    }
}


